home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / gl_draw.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  28KB  |  1,298 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21. // draw.c -- this is the only file outside the refresh that touches the
  22. // vid buffer
  23.  
  24. #include "quakedef.h"
  25.  
  26. #define GL_COLOR_INDEX8_EXT     0x80E5
  27.  
  28. extern unsigned char d_15to8table[65536];
  29.  
  30. cvar_t        gl_nobind = {"gl_nobind", "0"};
  31. cvar_t        gl_max_size = {"gl_max_size", "1024"};
  32. cvar_t        gl_picmip = {"gl_picmip", "0"};
  33.  
  34. byte        *draw_chars;                // 8*8 graphic characters
  35. qpic_t        *draw_disc;
  36. qpic_t        *draw_backtile;
  37.  
  38. int            translate_texture;
  39. int            char_texture;
  40.  
  41. typedef struct
  42. {
  43.     int        texnum;
  44.     float    sl, tl, sh, th;
  45. } glpic_t;
  46.  
  47. byte        conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
  48. qpic_t        *conback = (qpic_t *)&conback_buffer;
  49.  
  50. int        gl_lightmap_format = 4;
  51. int        gl_solid_format = 3;
  52. int        gl_alpha_format = 4;
  53.  
  54. int        gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
  55. int        gl_filter_max = GL_LINEAR;
  56.  
  57.  
  58. int        texels;
  59.  
  60. typedef struct
  61. {
  62.     int        texnum;
  63.     char    identifier[64];
  64.     int        width, height;
  65.     qboolean    mipmap;
  66. } gltexture_t;
  67.  
  68. #define    MAX_GLTEXTURES    1024
  69. gltexture_t    gltextures[MAX_GLTEXTURES];
  70. int            numgltextures;
  71.  
  72.  
  73. void GL_Bind (int texnum)
  74. {
  75.     if (gl_nobind.value)
  76.         texnum = char_texture;
  77.     if (currenttexture == texnum)
  78.         return;
  79.     currenttexture = texnum;
  80. #ifdef _WIN32
  81.     bindTexFunc (GL_TEXTURE_2D, texnum);
  82. #else
  83.     glBindTexture(GL_TEXTURE_2D, texnum);
  84. #endif
  85. }
  86.  
  87.  
  88. /*
  89. =============================================================================
  90.  
  91.   scrap allocation
  92.  
  93.   Allocate all the little status bar obejcts into a single texture
  94.   to crutch up stupid hardware / drivers
  95.  
  96. =============================================================================
  97. */
  98.  
  99. #define    MAX_SCRAPS        2
  100. #define    BLOCK_WIDTH        256
  101. #define    BLOCK_HEIGHT    256
  102.  
  103. int            scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
  104. byte        scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
  105. qboolean    scrap_dirty;
  106. int            scrap_texnum;
  107.  
  108. // returns a texture number and the position inside it
  109. int Scrap_AllocBlock (int w, int h, int *x, int *y)
  110. {
  111.     int        i, j;
  112.     int        best, best2;
  113.     int        bestx;
  114.     int        texnum;
  115.  
  116.     for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
  117.     {
  118.         best = BLOCK_HEIGHT;
  119.  
  120.         for (i=0 ; i<BLOCK_WIDTH-w ; i++)
  121.         {
  122.             best2 = 0;
  123.  
  124.             for (j=0 ; j<w ; j++)
  125.             {
  126.                 if (scrap_allocated[texnum][i+j] >= best)
  127.                     break;
  128.                 if (scrap_allocated[texnum][i+j] > best2)
  129.                     best2 = scrap_allocated[texnum][i+j];
  130.             }
  131.             if (j == w)
  132.             {    // this is a valid spot
  133.                 *x = i;
  134.                 *y = best = best2;
  135.             }
  136.         }
  137.  
  138.         if (best + h > BLOCK_HEIGHT)
  139.             continue;
  140.  
  141.         for (i=0 ; i<w ; i++)
  142.             scrap_allocated[texnum][*x + i] = best + h;
  143.  
  144.         return texnum;
  145.     }
  146.  
  147.     Sys_Error ("Scrap_AllocBlock: full");
  148. }
  149.  
  150. int    scrap_uploads;
  151.  
  152. void Scrap_Upload (void)
  153. {
  154.     int        texnum;
  155.  
  156.     scrap_uploads++;
  157.  
  158.     for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++) {
  159.         GL_Bind(scrap_texnum + texnum);
  160.         GL_Upload8 (scrap_texels[texnum], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
  161.     }
  162.     scrap_dirty = false;
  163. }
  164.  
  165. //=============================================================================
  166. /* Support Routines */
  167.  
  168. typedef struct cachepic_s
  169. {
  170.     char        name[MAX_QPATH];
  171.     qpic_t        pic;
  172.     byte        padding[32];    // for appended glpic
  173. } cachepic_t;
  174.  
  175. #define    MAX_CACHED_PICS        128
  176. cachepic_t    menu_cachepics[MAX_CACHED_PICS];
  177. int            menu_numcachepics;
  178.  
  179. byte        menuplyr_pixels[4096];
  180.  
  181. int        pic_texels;
  182. int        pic_count;
  183.  
  184. qpic_t *Draw_PicFromWad (char *name)
  185. {
  186.     qpic_t    *p;
  187.     glpic_t    *gl;
  188.  
  189.     p = W_GetLumpName (name);
  190.     gl = (glpic_t *)p->data;
  191.  
  192.     // load little ones into the scrap
  193.     if (p->width < 64 && p->height < 64)
  194.     {
  195.         int        x, y;
  196.         int        i, j, k;
  197.         int        texnum;
  198.  
  199.         texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
  200.         scrap_dirty = true;
  201.         k = 0;
  202.         for (i=0 ; i<p->height ; i++)
  203.             for (j=0 ; j<p->width ; j++, k++)
  204.                 scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
  205.         texnum += scrap_texnum;
  206.         gl->texnum = texnum;
  207.         gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
  208.         gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
  209.         gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
  210.         gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
  211.  
  212.         pic_count++;
  213.         pic_texels += p->width*p->height;
  214.     }
  215.     else
  216.     {
  217.         gl->texnum = GL_LoadPicTexture (p);
  218.         gl->sl = 0;
  219.         gl->sh = 1;
  220.         gl->tl = 0;
  221.         gl->th = 1;
  222.     }
  223.     return p;
  224. }
  225.  
  226.  
  227. /*
  228. ================
  229. Draw_CachePic
  230. ================
  231. */
  232. qpic_t    *Draw_CachePic (char *path)
  233. {
  234.     cachepic_t    *pic;
  235.     int            i;
  236.     qpic_t        *dat;
  237.     glpic_t        *gl;
  238.  
  239.     for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
  240.         if (!strcmp (path, pic->name))
  241.             return &pic->pic;
  242.  
  243.     if (menu_numcachepics == MAX_CACHED_PICS)
  244.         Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
  245.     menu_numcachepics++;
  246.     strcpy (pic->name, path);
  247.  
  248. //
  249. // load the pic from disk
  250. //
  251.     dat = (qpic_t *)COM_LoadTempFile (path);    
  252.     if (!dat)
  253.         Sys_Error ("Draw_CachePic: failed to load %s", path);
  254.     SwapPic (dat);
  255.  
  256.     // HACK HACK HACK --- we need to keep the bytes for
  257.     // the translatable player picture just for the menu
  258.     // configuration dialog
  259.     if (!strcmp (path, "gfx/menuplyr.lmp"))
  260.         memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
  261.  
  262.     pic->pic.width = dat->width;
  263.     pic->pic.height = dat->height;
  264.  
  265.     gl = (glpic_t *)pic->pic.data;
  266.     gl->texnum = GL_LoadPicTexture (dat);
  267.     gl->sl = 0;
  268.     gl->sh = 1;
  269.     gl->tl = 0;
  270.     gl->th = 1;
  271.  
  272.     return &pic->pic;
  273. }
  274.  
  275.  
  276. void Draw_CharToConback (int num, byte *dest)
  277. {
  278.     int        row, col;
  279.     byte    *source;
  280.     int        drawline;
  281.     int        x;
  282.  
  283.     row = num>>4;
  284.     col = num&15;
  285.     source = draw_chars + (row<<10) + (col<<3);
  286.  
  287.     drawline = 8;
  288.  
  289.     while (drawline--)
  290.     {
  291.         for (x=0 ; x<8 ; x++)
  292.             if (source[x] != 255)
  293.                 dest[x] = 0x60 + source[x];
  294.         source += 128;
  295.         dest += 320;
  296.     }
  297.  
  298. }
  299.  
  300. typedef struct
  301. {
  302.     char *name;
  303.     int    minimize, maximize;
  304. } glmode_t;
  305.  
  306. glmode_t modes[] = {
  307.     {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
  308.     {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
  309.     {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
  310.     {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
  311.     {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
  312.     {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
  313. };
  314.  
  315. /*
  316. ===============
  317. Draw_TextureMode_f
  318. ===============
  319. */
  320. void Draw_TextureMode_f (void)
  321. {
  322.     int        i;
  323.     gltexture_t    *glt;
  324.  
  325.     if (Cmd_Argc() == 1)
  326.     {
  327.         for (i=0 ; i< 6 ; i++)
  328.             if (gl_filter_min == modes[i].minimize)
  329.             {
  330.                 Con_Printf ("%s\n", modes[i].name);
  331.                 return;
  332.             }
  333.         Con_Printf ("current filter is unknown???\n");
  334.         return;
  335.     }
  336.  
  337.     for (i=0 ; i< 6 ; i++)
  338.     {
  339.         if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
  340.             break;
  341.     }
  342.     if (i == 6)
  343.     {
  344.         Con_Printf ("bad filter name\n");
  345.         return;
  346.     }
  347.  
  348.     gl_filter_min = modes[i].minimize;
  349.     gl_filter_max = modes[i].maximize;
  350.  
  351.     // change all the existing mipmap texture objects
  352.     for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
  353.     {
  354.         if (glt->mipmap)
  355.         {
  356.             GL_Bind (glt->texnum);
  357.             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  358.             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  359.         }
  360.     }
  361. }
  362.  
  363. /*
  364. ===============
  365. Draw_Init
  366. ===============
  367. */
  368. void Draw_Init (void)
  369. {
  370.     int        i;
  371.     qpic_t    *cb;
  372.     byte    *dest, *src;
  373.     int        x, y;
  374.     char    ver[40];
  375.     glpic_t    *gl;
  376.     int        start;
  377.     byte    *ncdata;
  378.     int        f, fstep;
  379.  
  380.  
  381.     Cvar_RegisterVariable (&gl_nobind);
  382.     Cvar_RegisterVariable (&gl_max_size);
  383.     Cvar_RegisterVariable (&gl_picmip);
  384.  
  385.     // 3dfx can only handle 256 wide textures
  386.     if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) ||
  387.         strstr((char *)gl_renderer, "Glide"))
  388.         Cvar_Set ("gl_max_size", "256");
  389.  
  390.     Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
  391.  
  392.     // load the console background and the charset
  393.     // by hand, because we need to write the version
  394.     // string into the background before turning
  395.     // it into a texture
  396.     draw_chars = W_GetLumpName ("conchars");
  397.     for (i=0 ; i<256*64 ; i++)
  398.         if (draw_chars[i] == 0)
  399.             draw_chars[i] = 255;    // proper transparent color
  400.  
  401.     // now turn them into textures
  402.     char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true);
  403.  
  404.     start = Hunk_LowMark();
  405.  
  406.     cb = (qpic_t *)COM_LoadTempFile ("gfx/conback.lmp");    
  407.     if (!cb)
  408.         Sys_Error ("Couldn't load gfx/conback.lmp");
  409.     SwapPic (cb);
  410.  
  411.     // hack the version number directly into the pic
  412. #if defined(__linux__)
  413.     sprintf (ver, "(Linux %2.2f, gl %4.2f) %4.2f", (float)LINUX_VERSION, (float)GLQUAKE_VERSION, (float)VERSION);
  414. #else
  415.     sprintf (ver, "(gl %4.2f) %4.2f", (float)GLQUAKE_VERSION, (float)VERSION);
  416. #endif
  417.     dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver);
  418.     y = strlen(ver);
  419.     for (x=0 ; x<y ; x++)
  420.         Draw_CharToConback (ver[x], dest+(x<<3));
  421.  
  422. #if 0
  423.     conback->width = vid.conwidth;
  424.     conback->height = vid.conheight;
  425.  
  426.      // scale console to vid size
  427.      dest = ncdata = Hunk_AllocName(vid.conwidth * vid.conheight, "conback");
  428.  
  429.      for (y=0 ; y<vid.conheight ; y++, dest += vid.conwidth)
  430.      {
  431.          src = cb->data + cb->width * (y*cb->height/vid.conheight);
  432.          if (vid.conwidth == cb->width)
  433.              memcpy (dest, src, vid.conwidth);
  434.          else
  435.          {
  436.              f = 0;
  437.              fstep = cb->width*0x10000/vid.conwidth;
  438.              for (x=0 ; x<vid.conwidth ; x+=4)
  439.              {
  440.                  dest[x] = src[f>>16];
  441.                  f += fstep;
  442.                  dest[x+1] = src[f>>16];
  443.                  f += fstep;
  444.                  dest[x+2] = src[f>>16];
  445.                  f += fstep;
  446.                  dest[x+3] = src[f>>16];
  447.                  f += fstep;
  448.              }
  449.          }
  450.      }
  451. #else
  452.     conback->width = cb->width;
  453.     conback->height = cb->height;
  454.     ncdata = cb->data;
  455. #endif
  456.  
  457.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  458.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  459.  
  460.     gl = (glpic_t *)conback->data;
  461.     gl->texnum = GL_LoadTexture ("conback", conback->width, conback->height, ncdata, false, false);
  462.     gl->sl = 0;
  463.     gl->sh = 1;
  464.     gl->tl = 0;
  465.     gl->th = 1;
  466.     conback->width = vid.width;
  467.     conback->height = vid.height;
  468.  
  469.     // free loaded console
  470.     Hunk_FreeToLowMark(start);
  471.  
  472.     // save a texture slot for translated picture
  473.     translate_texture = texture_extension_number++;
  474.  
  475.     // save slots for scraps
  476.     scrap_texnum = texture_extension_number;
  477.     texture_extension_number += MAX_SCRAPS;
  478.  
  479.     //
  480.     // get the other pics we need
  481.     //
  482.     draw_disc = Draw_PicFromWad ("disc");
  483.     draw_backtile = Draw_PicFromWad ("backtile");
  484. }
  485.  
  486.  
  487.  
  488. /*
  489. ================
  490. Draw_Character
  491.  
  492. Draws one 8*8 graphics character with 0 being transparent.
  493. It can be clipped to the top of the screen to allow the console to be
  494. smoothly scrolled off.
  495. ================
  496. */
  497. void Draw_Character (int x, int y, int num)
  498. {
  499.     byte            *dest;
  500.     byte            *source;
  501.     unsigned short    *pusdest;
  502.     int                drawline;    
  503.     int                row, col;
  504.     float            frow, fcol, size;
  505.  
  506.     if (num == 32)
  507.         return;        // space
  508.  
  509.     num &= 255;
  510.     
  511.     if (y <= -8)
  512.         return;            // totally off screen
  513.  
  514.     row = num>>4;
  515.     col = num&15;
  516.  
  517.     frow = row*0.0625;
  518.     fcol = col*0.0625;
  519.     size = 0.0625;
  520.  
  521.     GL_Bind (char_texture);
  522.  
  523.     glBegin (GL_QUADS);
  524.     glTexCoord2f (fcol, frow);
  525.     glVertex2f (x, y);
  526.     glTexCoord2f (fcol + size, frow);
  527.     glVertex2f (x+8, y);
  528.     glTexCoord2f (fcol + size, frow + size);
  529.     glVertex2f (x+8, y+8);
  530.     glTexCoord2f (fcol, frow + size);
  531.     glVertex2f (x, y+8);
  532.     glEnd ();
  533. }
  534.  
  535. /*
  536. ================
  537. Draw_String
  538. ================
  539. */
  540. void Draw_String (int x, int y, char *str)
  541. {
  542.     while (*str)
  543.     {
  544.         Draw_Character (x, y, *str);
  545.         str++;
  546.         x += 8;
  547.     }
  548. }
  549.  
  550. /*
  551. ================
  552. Draw_DebugChar
  553.  
  554. Draws a single character directly to the upper right corner of the screen.
  555. This is for debugging lockups by drawing different chars in different parts
  556. of the code.
  557. ================
  558. */
  559. void Draw_DebugChar (char num)
  560. {
  561. }
  562.  
  563. /*
  564. =============
  565. Draw_AlphaPic
  566. =============
  567. */
  568. void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
  569. {
  570.     byte            *dest, *source;
  571.     unsigned short    *pusdest;
  572.     int                v, u;
  573.     glpic_t            *gl;
  574.  
  575.     if (scrap_dirty)
  576.         Scrap_Upload ();
  577.     gl = (glpic_t *)pic->data;
  578.     glDisable(GL_ALPHA_TEST);
  579.     glEnable (GL_BLEND);
  580. //    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  581. //    glCullFace(GL_FRONT);
  582.     glColor4f (1,1,1,alpha);
  583.     GL_Bind (gl->texnum);
  584.     glBegin (GL_QUADS);
  585.     glTexCoord2f (gl->sl, gl->tl);
  586.     glVertex2f (x, y);
  587.     glTexCoord2f (gl->sh, gl->tl);
  588.     glVertex2f (x+pic->width, y);
  589.     glTexCoord2f (gl->sh, gl->th);
  590.     glVertex2f (x+pic->width, y+pic->height);
  591.     glTexCoord2f (gl->sl, gl->th);
  592.     glVertex2f (x, y+pic->height);
  593.     glEnd ();
  594.     glColor4f (1,1,1,1);
  595.     glEnable(GL_ALPHA_TEST);
  596.     glDisable (GL_BLEND);
  597. }
  598.  
  599.  
  600. /*
  601. =============
  602. Draw_Pic
  603. =============
  604. */
  605. void Draw_Pic (int x, int y, qpic_t *pic)
  606. {
  607.     byte            *dest, *source;
  608.     unsigned short    *pusdest;
  609.     int                v, u;
  610.     glpic_t            *gl;
  611.  
  612.     if (scrap_dirty)
  613.         Scrap_Upload ();
  614.     gl = (glpic_t *)pic->data;
  615.     glColor4f (1,1,1,1);
  616.     GL_Bind (gl->texnum);
  617.     glBegin (GL_QUADS);
  618.     glTexCoord2f (gl->sl, gl->tl);
  619.     glVertex2f (x, y);
  620.     glTexCoord2f (gl->sh, gl->tl);
  621.     glVertex2f (x+pic->width, y);
  622.     glTexCoord2f (gl->sh, gl->th);
  623.     glVertex2f (x+pic->width, y+pic->height);
  624.     glTexCoord2f (gl->sl, gl->th);
  625.     glVertex2f (x, y+pic->height);
  626.     glEnd ();
  627. }
  628.  
  629.  
  630. /*
  631. =============
  632. Draw_TransPic
  633. =============
  634. */
  635. void Draw_TransPic (int x, int y, qpic_t *pic)
  636. {
  637.     byte    *dest, *source, tbyte;
  638.     unsigned short    *pusdest;
  639.     int                v, u;
  640.  
  641.     if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
  642.          (unsigned)(y + pic->height) > vid.height)
  643.     {
  644.         Sys_Error ("Draw_TransPic: bad coordinates");
  645.     }
  646.         
  647.     Draw_Pic (x, y, pic);
  648. }
  649.  
  650.  
  651. /*
  652. =============
  653. Draw_TransPicTranslate
  654.  
  655. Only used for the player color selection menu
  656. =============
  657. */
  658. void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
  659. {
  660.     int                v, u, c;
  661.     unsigned        trans[64*64], *dest;
  662.     byte            *src;
  663.     int                p;
  664.  
  665.     GL_Bind (translate_texture);
  666.  
  667.     c = pic->width * pic->height;
  668.  
  669.     dest = trans;
  670.     for (v=0 ; v<64 ; v++, dest += 64)
  671.     {
  672.         src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
  673.         for (u=0 ; u<64 ; u++)
  674.         {
  675.             p = src[(u*pic->width)>>6];
  676.             if (p == 255)
  677.                 dest[u] = p;
  678.             else
  679.                 dest[u] =  d_8to24table[translation[p]];
  680.         }
  681.     }
  682.  
  683.     glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  684.  
  685.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  686.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  687.  
  688.     glColor3f (1,1,1);
  689.     glBegin (GL_QUADS);
  690.     glTexCoord2f (0, 0);
  691.     glVertex2f (x, y);
  692.     glTexCoord2f (1, 0);
  693.     glVertex2f (x+pic->width, y);
  694.     glTexCoord2f (1, 1);
  695.     glVertex2f (x+pic->width, y+pic->height);
  696.     glTexCoord2f (0, 1);
  697.     glVertex2f (x, y+pic->height);
  698.     glEnd ();
  699. }
  700.  
  701.  
  702. /*
  703. ================
  704. Draw_ConsoleBackground
  705.  
  706. ================
  707. */
  708. void Draw_ConsoleBackground (int lines)
  709. {
  710.     int y = (vid.height * 3) >> 2;
  711.  
  712.     if (lines > y)
  713.         Draw_Pic(0, lines - vid.height, conback);
  714.     else
  715.         Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
  716. }
  717.  
  718.  
  719. /*
  720. =============
  721. Draw_TileClear
  722.  
  723. This repeats a 64*64 tile graphic to fill the screen around a sized down
  724. refresh window.
  725. =============
  726. */
  727. void Draw_TileClear (int x, int y, int w, int h)
  728. {
  729.     glColor3f (1,1,1);
  730.     GL_Bind (*(int *)draw_backtile->data);
  731.     glBegin (GL_QUADS);
  732.     glTexCoord2f (x/64.0, y/64.0);
  733.     glVertex2f (x, y);
  734.     glTexCoord2f ( (x+w)/64.0, y/64.0);
  735.     glVertex2f (x+w, y);
  736.     glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
  737.     glVertex2f (x+w, y+h);
  738.     glTexCoord2f ( x/64.0, (y+h)/64.0 );
  739.     glVertex2f (x, y+h);
  740.     glEnd ();
  741. }
  742.  
  743.  
  744. /*
  745. =============
  746. Draw_Fill
  747.  
  748. Fills a box of pixels with a single color
  749. =============
  750. */
  751. void Draw_Fill (int x, int y, int w, int h, int c)
  752. {
  753.     glDisable (GL_TEXTURE_2D);
  754.     glColor3f (host_basepal[c*3]/255.0,
  755.         host_basepal[c*3+1]/255.0,
  756.         host_basepal[c*3+2]/255.0);
  757.  
  758.     glBegin (GL_QUADS);
  759.  
  760.     glVertex2f (x,y);
  761.     glVertex2f (x+w, y);
  762.     glVertex2f (x+w, y+h);
  763.     glVertex2f (x, y+h);
  764.  
  765.     glEnd ();
  766.     glColor3f (1,1,1);
  767.     glEnable (GL_TEXTURE_2D);
  768. }
  769. //=============================================================================
  770.  
  771. /*
  772. ================
  773. Draw_FadeScreen
  774.  
  775. ================
  776. */
  777. void Draw_FadeScreen (void)
  778. {
  779.     glEnable (GL_BLEND);
  780.     glDisable (GL_TEXTURE_2D);
  781.     glColor4f (0, 0, 0, 0.8);
  782.     glBegin (GL_QUADS);
  783.  
  784.     glVertex2f (0,0);
  785.     glVertex2f (vid.width, 0);
  786.     glVertex2f (vid.width, vid.height);
  787.     glVertex2f (0, vid.height);
  788.  
  789.     glEnd ();
  790.     glColor4f (1,1,1,1);
  791.     glEnable (GL_TEXTURE_2D);
  792.     glDisable (GL_BLEND);
  793.  
  794.     Sbar_Changed();
  795. }
  796.  
  797. //=============================================================================
  798.  
  799. /*
  800. ================
  801. Draw_BeginDisc
  802.  
  803. Draws the little blue disc in the corner of the screen.
  804. Call before beginning any disc IO.
  805. ================
  806. */
  807. void Draw_BeginDisc (void)
  808. {
  809.     if (!draw_disc)
  810.         return;
  811.     glDrawBuffer  (GL_FRONT);
  812.     Draw_Pic (vid.width - 24, 0, draw_disc);
  813.     glDrawBuffer  (GL_BACK);
  814. }
  815.  
  816.  
  817. /*
  818. ================
  819. Draw_EndDisc
  820.  
  821. Erases the disc icon.
  822. Call after completing any disc IO
  823. ================
  824. */
  825. void Draw_EndDisc (void)
  826. {
  827. }
  828.  
  829. /*
  830. ================
  831. GL_Set2D
  832.  
  833. Setup as if the screen was 320*200
  834. ================
  835. */
  836. void GL_Set2D (void)
  837. {
  838.     glViewport (glx, gly, glwidth, glheight);
  839.  
  840.     glMatrixMode(GL_PROJECTION);
  841.     glLoadIdentity ();
  842.     glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
  843.  
  844.     glMatrixMode(GL_MODELVIEW);
  845.     glLoadIdentity ();
  846.  
  847.     glDisable (GL_DEPTH_TEST);
  848.     glDisable (GL_CULL_FACE);
  849.     glDisable (GL_BLEND);
  850.     glEnable (GL_ALPHA_TEST);
  851. //    glDisable (GL_ALPHA_TEST);
  852.  
  853.     glColor4f (1,1,1,1);
  854. }
  855.  
  856. //====================================================================
  857.  
  858. /*
  859. ================
  860. GL_FindTexture
  861. ================
  862. */
  863. int GL_FindTexture (char *identifier)
  864. {
  865.     int        i;
  866.     gltexture_t    *glt;
  867.  
  868.     for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
  869.     {
  870.         if (!strcmp (identifier, glt->identifier))
  871.             return gltextures[i].texnum;
  872.     }
  873.  
  874.     return -1;
  875. }
  876.  
  877. /*
  878. ================
  879. GL_ResampleTexture
  880. ================
  881. */
  882. void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight)
  883. {
  884.     int        i, j;
  885.     unsigned    *inrow;
  886.     unsigned    frac, fracstep;
  887.  
  888.     fracstep = inwidth*0x10000/outwidth;
  889.     for (i=0 ; i<outheight ; i++, out += outwidth)
  890.     {
  891.         inrow = in + inwidth*(i*inheight/outheight);
  892.         frac = fracstep >> 1;
  893.         for (j=0 ; j<outwidth ; j+=4)
  894.         {
  895.             out[j] = inrow[frac>>16];
  896.             frac += fracstep;
  897.             out[j+1] = inrow[frac>>16];
  898.             frac += fracstep;
  899.             out[j+2] = inrow[frac>>16];
  900.             frac += fracstep;
  901.             out[j+3] = inrow[frac>>16];
  902.             frac += fracstep;
  903.         }
  904.     }
  905. }
  906.  
  907. /*
  908. ================
  909. GL_Resample8BitTexture -- JACK
  910. ================
  911. */
  912. void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out,  int outwidth, int outheight)
  913. {
  914.     int        i, j;
  915.     unsigned    char *inrow;
  916.     unsigned    frac, fracstep;
  917.  
  918.     fracstep = inwidth*0x10000/outwidth;
  919.     for (i=0 ; i<outheight ; i++, out += outwidth)
  920.     {
  921.         inrow = in + inwidth*(i*inheight/outheight);
  922.         frac = fracstep >> 1;
  923.         for (j=0 ; j<outwidth ; j+=4)
  924.         {
  925.             out[j] = inrow[frac>>16];
  926.             frac += fracstep;
  927.             out[j+1] = inrow[frac>>16];
  928.             frac += fracstep;
  929.             out[j+2] = inrow[frac>>16];
  930.             frac += fracstep;
  931.             out[j+3] = inrow[frac>>16];
  932.             frac += fracstep;
  933.         }
  934.     }
  935. }
  936.  
  937.  
  938. /*
  939. ================
  940. GL_MipMap
  941.  
  942. Operates in place, quartering the size of the texture
  943. ================
  944. */
  945. void GL_MipMap (byte *in, int width, int height)
  946. {
  947.     int        i, j;
  948.     byte    *out;
  949.  
  950.     width <<=2;
  951.     height >>= 1;
  952.     out = in;
  953.     for (i=0 ; i<height ; i++, in+=width)
  954.     {
  955.         for (j=0 ; j<width ; j+=8, out+=4, in+=8)
  956.         {
  957.             out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
  958.             out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
  959.             out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
  960.             out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
  961.         }
  962.     }
  963. }
  964.  
  965. /*
  966. ================
  967. GL_MipMap8Bit
  968.  
  969. Mipping for 8 bit textures
  970. ================
  971. */
  972. void GL_MipMap8Bit (byte *in, int width, int height)
  973. {
  974.     int        i, j;
  975.     unsigned short     r,g,b;
  976.     byte    *out, *at1, *at2, *at3, *at4;
  977.  
  978. //    width <<=2;
  979.     height >>= 1;
  980.     out = in;
  981.     for (i=0 ; i<height ; i++, in+=width)
  982.     {
  983.         for (j=0 ; j<width ; j+=2, out+=1, in+=2)
  984.         {
  985.             at1 = (byte *) (d_8to24table + in[0]);
  986.             at2 = (byte *) (d_8to24table + in[1]);
  987.             at3 = (byte *) (d_8to24table + in[width+0]);
  988.             at4 = (byte *) (d_8to24table + in[width+1]);
  989.  
  990.              r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
  991.              g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
  992.              b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
  993.  
  994.             out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
  995.         }
  996.     }
  997. }
  998.  
  999. /*
  1000. ===============
  1001. GL_Upload32
  1002. ===============
  1003. */
  1004. void GL_Upload32 (unsigned *data, int width, int height,  qboolean mipmap, qboolean alpha)
  1005. {
  1006.     int            samples;
  1007. static    unsigned    scaled[1024*512];    // [512*256];
  1008.     int            scaled_width, scaled_height;
  1009.  
  1010.     for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
  1011.         ;
  1012.     for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
  1013.         ;
  1014.  
  1015.     scaled_width >>= (int)gl_picmip.value;
  1016.     scaled_height >>= (int)gl_picmip.value;
  1017.  
  1018.     if (scaled_width > gl_max_size.value)
  1019.         scaled_width = gl_max_size.value;
  1020.     if (scaled_height > gl_max_size.value)
  1021.         scaled_height = gl_max_size.value;
  1022.  
  1023.     if (scaled_width * scaled_height > sizeof(scaled)/4)
  1024.         Sys_Error ("GL_LoadTexture: too big");
  1025.  
  1026.     samples = alpha ? gl_alpha_format : gl_solid_format;
  1027.  
  1028. #if 0
  1029.     if (mipmap)
  1030.         gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  1031.     else if (scaled_width == width && scaled_height == height)
  1032.         glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  1033.     else
  1034.     {
  1035.         gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
  1036.             scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
  1037.         glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
  1038.     }
  1039. #else
  1040. texels += scaled_width * scaled_height;
  1041.  
  1042.     if (scaled_width == width && scaled_height == height)
  1043.     {
  1044.         if (!mipmap)
  1045.         {
  1046.             glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  1047.             goto done;
  1048.         }
  1049.         memcpy (scaled, data, width*height*4);
  1050.     }
  1051.     else
  1052.         GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
  1053.  
  1054.     glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
  1055.     if (mipmap)
  1056.     {
  1057.         int        miplevel;
  1058.  
  1059.         miplevel = 0;
  1060.         while (scaled_width > 1 || scaled_height > 1)
  1061.         {
  1062.             GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
  1063.             scaled_width >>= 1;
  1064.             scaled_height >>= 1;
  1065.             if (scaled_width < 1)
  1066.                 scaled_width = 1;
  1067.             if (scaled_height < 1)
  1068.                 scaled_height = 1;
  1069.             miplevel++;
  1070.             glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
  1071.         }
  1072.     }
  1073. done: ;
  1074. #endif
  1075.  
  1076.  
  1077.     if (mipmap)
  1078.     {
  1079.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  1080.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  1081.     }
  1082.     else
  1083.     {
  1084.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
  1085.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  1086.     }
  1087. }
  1088.  
  1089. void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap, qboolean alpha) 
  1090. {
  1091.     int            i, s;
  1092.     qboolean    noalpha;
  1093.     int            p;
  1094.     static unsigned j;
  1095.     int            samples;
  1096.     static    unsigned char scaled[1024*512];    // [512*256];
  1097.     int            scaled_width, scaled_height;
  1098.  
  1099.     s = width*height;
  1100.     // if there are no transparent pixels, make it a 3 component
  1101.     // texture even if it was specified as otherwise
  1102.     if (alpha)
  1103.     {
  1104.         noalpha = true;
  1105.         for (i=0 ; i<s ; i++)
  1106.         {
  1107.             if (data[i] == 255)
  1108.                 noalpha = false;
  1109.         }
  1110.  
  1111.         if (alpha && noalpha)
  1112.             alpha = false;
  1113.     }
  1114.     for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
  1115.         ;
  1116.     for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
  1117.         ;
  1118.  
  1119.     scaled_width >>= (int)gl_picmip.value;
  1120.     scaled_height >>= (int)gl_picmip.value;
  1121.  
  1122.     if (scaled_width > gl_max_size.value)
  1123.         scaled_width = gl_max_size.value;
  1124.     if (scaled_height > gl_max_size.value)
  1125.         scaled_height = gl_max_size.value;
  1126.  
  1127.     if (scaled_width * scaled_height > sizeof(scaled))
  1128.         Sys_Error ("GL_LoadTexture: too big");
  1129.  
  1130.     samples = 1; // alpha ? gl_alpha_format : gl_solid_format;
  1131.  
  1132.     texels += scaled_width * scaled_height;
  1133.  
  1134.     if (scaled_width == width && scaled_height == height)
  1135.     {
  1136.         if (!mipmap)
  1137.         {
  1138.             glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
  1139.             goto done;
  1140.         }
  1141.         memcpy (scaled, data, width*height);
  1142.     }
  1143.     else
  1144.         GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height);
  1145.  
  1146.     glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
  1147.     if (mipmap)
  1148.     {
  1149.         int        miplevel;
  1150.  
  1151.         miplevel = 0;
  1152.         while (scaled_width > 1 || scaled_height > 1)
  1153.         {
  1154.             GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
  1155.             scaled_width >>= 1;
  1156.             scaled_height >>= 1;
  1157.             if (scaled_width < 1)
  1158.                 scaled_width = 1;
  1159.             if (scaled_height < 1)
  1160.                 scaled_height = 1;
  1161.             miplevel++;
  1162.             glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
  1163.         }
  1164.     }
  1165. done: ;
  1166.  
  1167.  
  1168.     if (mipmap)
  1169.     {
  1170.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  1171.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  1172.     }
  1173.     else
  1174.     {
  1175.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
  1176.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  1177.     }
  1178. }
  1179.  
  1180. /*
  1181. ===============
  1182. GL_Upload8
  1183. ===============
  1184. */
  1185. void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha)
  1186. {
  1187. static    unsigned    trans[640*480];        // FIXME, temporary
  1188.     int            i, s;
  1189.     qboolean    noalpha;
  1190.     int            p;
  1191.  
  1192.     s = width*height;
  1193.     // if there are no transparent pixels, make it a 3 component
  1194.     // texture even if it was specified as otherwise
  1195.     if (alpha)
  1196.     {
  1197.         noalpha = true;
  1198.         for (i=0 ; i<s ; i++)
  1199.         {
  1200.             p = data[i];
  1201.             if (p == 255)
  1202.                 noalpha = false;
  1203.             trans[i] = d_8to24table[p];
  1204.         }
  1205.  
  1206.         if (alpha && noalpha)
  1207.             alpha = false;
  1208.     }
  1209.     else
  1210.     {
  1211.         if (s&3)
  1212.             Sys_Error ("GL_Upload8: s&3");
  1213.         for (i=0 ; i<s ; i+=4)
  1214.         {
  1215.             trans[i] = d_8to24table[data[i]];
  1216.             trans[i+1] = d_8to24table[data[i+1]];
  1217.             trans[i+2] = d_8to24table[data[i+2]];
  1218.             trans[i+3] = d_8to24table[data[i+3]];
  1219.         }
  1220.     }
  1221.  
  1222.      if (VID_Is8bit() && !alpha && (data!=scrap_texels[0])) {
  1223.          GL_Upload8_EXT (data, width, height, mipmap, alpha);
  1224.          return;
  1225.     }
  1226.     GL_Upload32 (trans, width, height, mipmap, alpha);
  1227. }
  1228.  
  1229. /*
  1230. ================
  1231. GL_LoadTexture
  1232. ================
  1233. */
  1234. int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha)
  1235. {
  1236.     qboolean    noalpha;
  1237.     int            i, p, s;
  1238.     gltexture_t    *glt;
  1239.  
  1240.     // see if the texture is allready present
  1241.     if (identifier[0])
  1242.     {
  1243.         for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
  1244.         {
  1245.             if (!strcmp (identifier, glt->identifier))
  1246.             {
  1247.                 if (width != glt->width || height != glt->height)
  1248.                     Sys_Error ("GL_LoadTexture: cache mismatch");
  1249.                 return gltextures[i].texnum;
  1250.             }
  1251.         }
  1252.     }
  1253.     else {
  1254.         glt = &gltextures[numgltextures];
  1255.         numgltextures++;
  1256.     }
  1257.  
  1258.     strcpy (glt->identifier, identifier);
  1259.     glt->texnum = texture_extension_number;
  1260.     glt->width = width;
  1261.     glt->height = height;
  1262.     glt->mipmap = mipmap;
  1263.  
  1264.     GL_Bind(texture_extension_number );
  1265.  
  1266.     GL_Upload8 (data, width, height, mipmap, alpha);
  1267.  
  1268.     texture_extension_number++;
  1269.  
  1270.     return texture_extension_number-1;
  1271. }
  1272.  
  1273. /*
  1274. ================
  1275. GL_LoadPicTexture
  1276. ================
  1277. */
  1278. int GL_LoadPicTexture (qpic_t *pic)
  1279. {
  1280.     return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true);
  1281. }
  1282.  
  1283. /****************************************/
  1284.  
  1285. static GLenum oldtarget = TEXTURE0_SGIS;
  1286.  
  1287. void GL_SelectTexture (GLenum target) 
  1288. {
  1289.     if (!gl_mtexable)
  1290.         return;
  1291.     qglSelectTextureSGIS(target);
  1292.     if (target == oldtarget) 
  1293.         return;
  1294.     cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture;
  1295.     currenttexture = cnttextures[target-TEXTURE0_SGIS];
  1296.     oldtarget = target;
  1297. }
  1298.